package QC.MessageBox.common;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Created by Andaren on 2017/4/20.
 * Used for: 表情转码
 */
public class EmojiUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(EmojiUtil.class);
    // 微信emoji
    private static String[] EMOJI_UNIFIED;          // unified UTF-16编码
    private static String[] EMOJI_DOCOMO;           // docomo
    private static String[] EMOJI_KDDI;             // kddi
    private static String[] EMOJI_SOFTBANK;         // softbank  杠uXXXX (已过时)(打印时为头像)
    private static String[] EMOJI_GOOGLE;           // google
    private static String[] EMOJI_SOFTBANK_UNICODE; // softbank转好的 杠uXXXX 形式
    private static String[] EMOJI_UNIFIED_UNICODE;  // unified 转换成 杠uXXXX 杠uXXXX 形式 (打印时为头像)

    // QQ表情
    private static String[] QQ_FACE_CODE;           // qq表情代码
    private static String[] QQ_FACE_TEXT;           // qq表情文字表述

    static {
        init();
    }

    public static void init() {

        try {
            InputStream inputStream = EmojiUtil.class.getClassLoader().getResourceAsStream("emoji.json");
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
            StringBuilder strSB = new StringBuilder();
            try {
                String line = null;
                while ((line = reader.readLine()) != null) {
                    strSB.append(line);
                }
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 初始化emoji各种编码数组
            JsonObject emojiJsonAll = new JsonObject(strSB.toString());
            // 获取微信emoji的json数组
            JsonArray wxemojiJsonArray = emojiJsonAll.getJsonArray("emoji_wx");
            Integer jsonArraySize = wxemojiJsonArray.size();
            EMOJI_UNIFIED = new String[jsonArraySize];
            EMOJI_DOCOMO = new String[jsonArraySize];
            EMOJI_KDDI = new String[jsonArraySize];
            EMOJI_SOFTBANK = new String[jsonArraySize];
            EMOJI_GOOGLE = new String[jsonArraySize];
            EMOJI_SOFTBANK_UNICODE = new String[jsonArraySize];
            EMOJI_UNIFIED_UNICODE = new String[jsonArraySize];
            if (jsonArraySize > 0) {
                for (int index = 0; index < jsonArraySize; index ++) {
                    JsonObject emojiJson = wxemojiJsonArray.getJsonObject(index);
                    EMOJI_UNIFIED[index] = emojiJson.getString("unified");
                    EMOJI_DOCOMO[index] = emojiJson.getString("docomo");
                    EMOJI_KDDI[index] = emojiJson.getString("kddi");
                    EMOJI_SOFTBANK[index] = emojiJson.getString("softbank");
                    EMOJI_GOOGLE[index] = emojiJson.getString("google");
                    EMOJI_SOFTBANK_UNICODE[index] = emojiJson.getString("softb_unicode");
                }
                // U+XXXX -> 0xXXXX
                for (int index = 0; index < jsonArraySize; index ++) {
                    String uStr = EMOJI_UNIFIED[index];
                    String[] uarray = uStr.split(" ");
                    char[] result;
                    if (uarray.length > 1) {
                        char[] c1 = Character.toChars(Integer.decode(uarray[0].replaceAll("U\\+", "0x")));
                        char[] c2 = Character.toChars(Integer.decode(uarray[1].replaceAll("U\\+", "0x")));
                        result = Arrays.copyOf(c1, c1.length+c2.length);
                        System.arraycopy(c2, 0, result, c1.length, c2.length);
                    } else {
                        result = Character.toChars(Integer.decode(uarray[0].replaceAll("U\\+", "0x")));
                    }
                    EMOJI_UNIFIED_UNICODE[index] = String.valueOf(result);
                }
                LOGGER.info("emoji表情库加载完毕");
            }
            // QQ 表情初始化
            JsonArray qqFaceJsonArray = emojiJsonAll.getJsonArray("qq_face_wx");
            Integer qqfaceCount = qqFaceJsonArray.size();
            if (qqfaceCount > 0) {
                QQ_FACE_CODE = new String[qqfaceCount];
                QQ_FACE_TEXT = new String[qqfaceCount];
                for (int index = 0; index < qqfaceCount; index ++) {
                    JsonObject qqfaceJson = qqFaceJsonArray.getJsonObject(index);
                    QQ_FACE_CODE[index] = qqfaceJson.getString("code");
                    QQ_FACE_TEXT[index] = qqfaceJson.getString("text");
                }
            }
        } catch (UnsupportedEncodingException e) {
            LOGGER.info("表情库初始化失败：" + e.getMessage());
        }
    }

    /**
     * 显示不可见字符的Unicode
     *
     * @param input
     * @return
     */
    public static String escapeUnicode(String input) {
        StringBuilder sb = new StringBuilder(input.length());
        @SuppressWarnings("resource")
        Formatter format = new Formatter(sb);
        for (char c : input.toCharArray()) {
            if (c < 128) {
                sb.append(c);
            } else {
                format.format("\\u%04x", (int) c);
            }
        }
        return sb.toString();
    }

    /**
     * 过滤处理WX消息
     *
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        // QQ表情转换
        source = EmojiUtil.changeQQFaceToText(source);
        // emoji表情转换
        source = EmojiUtil.changeSBEmojiToUnified(source);
        return source;
    }


    /**
     * 判断是否包含QQ表情
     *
     * @param content
     * @return
     */
    public static boolean isQqFace(String content) {

        boolean result = false;

        // 判断QQ表情的正则表达式
        String qqfaceRegex = ".*(/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:<W>|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:<L>|/:jump|/:shake|/:<O>|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>)*.*";
        Pattern p = Pattern.compile(qqfaceRegex);
        Matcher m = p.matcher(content);
        if (m.matches()) {
            result = true;
        }
        return result;
    }

    /**
     * 将微信消息中的QQ表情转换成文字描述
     * @param content
     * @return
     */
    public static String changeQQFaceToText(String content) {
        return content = StringUtils.replaceEach(content, QQ_FACE_CODE, QQ_FACE_TEXT);
    }

    /**
     * 判断是否包含emoji表情
     *      该方法只能判断Unifiled编码的emoji表情
     * @param source
     * @return
     */
    public static boolean containsEmoji(String source) {
        int len = source.length();
        boolean isEmoji = false;
        for (int i = 0; i < len; i++) {
            char hs = source.charAt(i);
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (source.length() > 1) {
                    char ls = source.charAt(i + 1);
                    int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        return true;
                    }
                }
            } else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
                    return true;
                } else if (0x2B05 <= hs && hs <= 0x2b07) {
                    return true;
                } else if (0x2934 <= hs && hs <= 0x2935) {
                    return true;
                } else if (0x3297 <= hs && hs <= 0x3299) {
                    return true;
                } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d
                        || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c
                        || hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) {
                    return true;
                }
                if (!isEmoji && source.length() > 1 && i < source.length() - 1) {
                    char ls = source.charAt(i + 1);
                    if (ls == 0x20e3) {
                        return true;
                    }
                }
            }
        }
        return isEmoji;
    }

    /**
     * 丢弃消息中的表情
     * @param msg
     * @return
     */
    public static String dropEmojiInMsg(String msg) {
        if(msg != null)
        {
            Pattern emoji = Pattern.compile ("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",Pattern.UNICODE_CASE | Pattern . CASE_INSENSITIVE ) ;
            Matcher emojiMatcher = emoji.matcher(msg);
            if ( emojiMatcher.find())
            {
                msg = emojiMatcher.replaceAll("*");
                return msg ;
            }
            return msg;
        }
        return msg;
    }

    public static String escapeEmoji(String msg) {
        StringBuffer sb = new StringBuffer();
        if(msg != null) {
            Pattern emoji = Pattern.compile ("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",Pattern.UNICODE_CASE | Pattern . CASE_INSENSITIVE ) ;
            Matcher emojiMatcher = emoji.matcher(msg);
            while ( emojiMatcher.find()) {
                emojiMatcher.appendReplacement(sb, encryptEmoji(emojiMatcher.group()));
            }
            emojiMatcher.appendTail(sb);
            return sb.toString();
        }
        return sb.toString();
    }

    /**
     * 将softbank编码的表情转化成unified编码表情
     * @param src
     * @return
     */
    public static String changeSBEmojiToUnified(String src) {
        if (EMOJI_UNIFIED_UNICODE.length == 0) {
            init();
        }
        return StringUtils.replaceEach(src, EMOJI_SOFTBANK_UNICODE, EMOJI_UNIFIED_UNICODE);
    }

    /**
     * 将unified编码的表情转化成softbank编码表情
     * @param src
     * @return
     */
    public static String changeEmojiFromUnifiedToSB(String src) {
        if (EMOJI_UNIFIED_UNICODE.length == 0) {
            init();
        }
        return StringUtils.replaceEach(src, EMOJI_UNIFIED_UNICODE, EMOJI_SOFTBANK_UNICODE);
    }

    /**
     * 对表情转换成unicode编码，方便存储
     * @param emoji
     * @return
     */
    public static String encryptEmoji(String emoji) {
        return StringEscapeUtils.escapeJava(emoji);
    }

    /**
     * 对表情还原编码
     * @param encryptEmoji
     * @return
     */
    public static String decodeEmoji(String encryptEmoji) {
        return  StringEscapeUtils.unescapeJava(encryptEmoji);
    }

    /**
     * 初始化emoji工具了需要的各种文件数据
     *      (确认在程序启动时，加载EmojiUtil类)
     */
    public static void startInit() {
        LOGGER.info("emojiUtil类开始加载");
    }

    public static void main(String args[]){





//        String emoji = String.valueOf(Character.toChars(0x00A9));
//        String e = unicode2unicodeString(emoji);
//        System.out.println(e);
//        String emoji2 = String.valueOf(Character.toChars(0x1F303));
//        String toWxMsg = "content=这是从" + emoji + "app发到微"+emoji2+"信的消息" + emoji + "[" + String.valueOf(new Date()) + "]" +
//                "&developerId=gh_0ddb7b0febec&openId=oVLn"+emoji2+"EuDtsa36n8QcDxvDfeXywoS8&type=text";
//        System.out.println("NORMALMSG->" + toWxMsg);
//        String msg = escapeEmoji(toWxMsg);
//        System.out.println("ENCODEMSG->" + msg);
//        System.out.println("DECODEMSG->" + decodeEmoji(msg));

        String emoji_soft = "\ud83d\udd25中";
        String emoji_unicode = "\\ud83d\\udd25";
        String encode = encryptEmoji(emoji_soft);
        String change = decodeEmoji(encode);
        System.out.println(encryptEmoji(emoji_soft));
        System.out.println(emoji_unicode);
    }

    /**
     * 将unicode码转为unicode字符串
     * @param string
     * @return
     */
    public static String unicode2unicodeString(String string) {

        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            StringBuilder hexSb = new StringBuilder(Integer.toHexString(c));
            while (hexSb.length() < 4) {
                hexSb.insert(0, "0");
            }
            // 转换为unicode
            unicode.append("\\u" + hexSb.toString());
        }
        return unicode.toString();
    }
}
